package com.common.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.common.exception.CreditException;
import com.common.exception.PCLServiceException;
import com.common.handler.PCLParamHandler;
import com.common.utils.beans.CreditResponseInfo;
import com.common.utils.beans.PCLResponseInfo;
import com.fasterxml.jackson.databind.ObjectMapper;

import net.sf.json.JSONObject;

/**
 * 发送http请求的http client
 * 
 * @author lj
 * @date 2017年6月8日 下午12:09:08
 */
@SuppressWarnings("deprecation")
public class HttpClientUtils {
	
	public static final String CHARSET = "UTF-8";
	
	public static final String DEFAULT_DATA_TYPE = "json";

	private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class.getName());

	private HttpClientUtils() {

	}
	
	/**
	 * 发送post请求
	 * @param url
	 * @param s
	 * @param dataType
	 * @return
	 * @author lj
	 * @throws IOException 
	 * @throws ClientProtocolException 
	 * @date 2017年6月8日 下午12:20:04
	 */
	public static String doPost(String url, Map<String, Object> params, String dataType) {
		return executePostHttp(url, params, dataType);
	}
	/**
	 * 发送post请求，对接pcl
	 * @param url
	 * @param params
	 * @param dataType
	 * @return
	 * @author lj
	 * @date 2017年6月8日 下午3:28:19
	 */
	public static PCLResponseInfo doPCLPost(String url, Map<String, Object> params){
		return doPCLPost(url, params, null);
	}
	
	/**
	 * 发送post请求，对接pcl
	 * @param url
	 * @param params 参数
	 * @param handler PCL参数处理器
	 * @return
	 * @author iuie
	 * @date 2017年7月25日 上午11:49:46
	 */
	public static PCLResponseInfo doPCLPost(String url, Map<String, Object> params, PCLParamHandler handler){
		String resp = doPost(url, params, handler);
		return processPCLResponse(resp);
	}
	
	/**
	 * 
	 * @Description: 银行卡认证接口
	 * @Title: doCreditPost
	 * @param @param url
	 * @param @param params
	 * @param @return     
	 * @return CreditResponseInfo     
	 * @Createdate 2017年6月30日  
	 * @throws
	 */
	public static CreditResponseInfo doCreditPost(String url, Map<String, Object> params){
		String resp = doPost(url, params);
		return processCreditResponse(resp);
	}
	
	/**
	 * 
	 * @Description: 身份证识别和银行卡识别 
	 * @Title: doCreditPost
	 * @param @param url
	 * @param @param parts
	 * @param @return     
	 * @return CreditResponseInfo     
	 * @Createdate 2017年6月30日  
	 * @throws
	 */
	public static CreditResponseInfo doCreditPost(String url, Part[] parts){
		String resp = identityHTTPClient(url, parts);         
		return processCreditResponse(resp);
	}
	
	/**
	 * 发送post请求，对接pcl
	 * @param url
	 * @param s
	 * @return
	 * @author lj
	 * @date 2017年6月8日 下午4:47:39
	 */
	public static PCLResponseInfo doPCLPost(String url, StringEntity s){
		String resp = doPost(url, s);
		return processPCLResponse(resp);
	}
	/**
	 * 发送post请求,dataType=json
	 * @param url
	 * @param s
	 * @return
	 * @author lj
	 * @date 2017年6月8日 下午12:20:04
	 */
	public static String doPost(String url, Map<String, Object> params)  {
		return executePostHttp(url, params, DEFAULT_DATA_TYPE);
	}
	
	/**
	 * 发送post请求,dataType=json
	 * @param url
	 * @param params
	 * @param handler 参数处理器
	 * @return
	 * @author iuie
	 * @date 2017年7月25日 上午11:51:55
	 */
	public static String doPost(String url, Map<String, Object> params, PCLParamHandler handler)  {
		return executePostHttp(url, params, DEFAULT_DATA_TYPE, handler);
	}

	/**
	 * 发送post请求，dataType=json
	 * @param url
	 * @param s
	 * @return
	 * @author lj
	 * @date 2017年6月8日 下午4:46:50
	 */
	public static String doPost(String url, StringEntity s) {
		return executePostHttp(url, s, DEFAULT_DATA_TYPE);
	}
	/**
	 * 发送post请求
	 * @param url
	 * @param s
	 * @param dataType
	 * @return
	 * @author lj
	 * @date 2017年6月8日 下午4:47:04
	 */
	public static String doPost(String url, StringEntity s, String dataType) {
		return executePostHttp(url, s, DEFAULT_DATA_TYPE);
	}
	
	/**
	 * 发送get请求
	 * @param url
	 * @param params
	 * @param dataType
	 * @return
	 * @author lj
	 * @date 2017年6月8日 下午12:20:13
	 */
	public static String doGet(String url, Map<String, Object> params, String dataType) throws ClientProtocolException {
		return executeGetHttp(url, params, dataType);
	}
	/**
	 * 发送get请求,dataType=json
	 * @param url
	 * @param params
	 * @param dataType
	 * @return
	 * @author lj
	 * @date 2017年6月8日 下午12:20:13
	 */
	public static String doGet(String url, Map<String, Object> params) {
		return executeGetHttp(url, params, DEFAULT_DATA_TYPE);
	}
	/**
	 * 发送get请求-对接pcl
	 * @param url
	 * @param params
	 * @return
	 * @author lj
	 * @date 2017年6月8日 下午4:06:31
	 */
	public static PCLResponseInfo doPCLGet(String url, Map<String, Object> params) {
		String resp = doGet(url, params);
		return processPCLResponse(resp);
	}
	
	/**
	 * 构造对接PCL接口参数--Post方式
	 * @param params
	 * @author lj
	 * @date 2017年6月19日 下午2:41:16
	 */
	public static Map<String, Object> buildPCLParam(Map<String, Object> params) {
		Map<String, Object> map = new HashMap<>();
		map.put("params", params);
		return map;
	}
	/**
	 * 构造对接PCL接口参数--Post方式
	 * @param params
	 * @author lj
	 * @date 2017年6月19日 下午2:41:16
	 */
	public static Map<String, Object> buildCreditParam(Map<String, Object> params, String account, String passwd) {
		Map<String, Object> map = new HashMap<>();
		map.put("params", params);
		map.put("account", account);
		map.put("passWord", passwd);
		return map;
	}
	
	/**
	 * 构造对接PCL接口参数--Post方式
	 * @param params
	 * @author lj
	 * @date 2017年6月19日 下午2:41:16
	 */
	public static Map<String, Object> buildPCLParam(Object params) {
		Map<String, Object> map = new HashMap<>();
		map.put("params", params);
		return map;
	}
	
	private static HttpClient getDefaultHttpClient() {
		HttpClient client = new DefaultHttpClient();
		client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);// 连接时间
		client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);// 读数据超时时间
		return client;
	}
	/*
	 * 发送GET请求
	 */
	private static String executeGetHttp(String url, Map<String, Object> params, String dataType) {
		try {
			String respSt = "";
			
			if (params != null && !params.isEmpty()) {
	            List<NameValuePair> pairs = new ArrayList<NameValuePair>(params.size());
	            for (String key : params.keySet()) {
	            	pairs.add(new BasicNameValuePair(key, params.get(key).toString()));
	            }
	            if (url.contains("?")) {
	            	url += "&" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, CHARSET));
	            } else {
	            	url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, CHARSET));
	            }
	        }
			
			HttpClient client = getDefaultHttpClient();
			HttpGet get = new HttpGet(url);
			
			HttpResponse resp = client.execute(get);
			HttpEntity entity = resp.getEntity();
			BufferedReader reader = new BufferedReader(
					new InputStreamReader(entity.getContent(), CHARSET));
			String buffer = reader.readLine();
			if (buffer != null) {
				if (dataType.equalsIgnoreCase("JSON")) {
					JSONObject json_bak = JSONObject.fromObject(buffer);
					logger.info(json_bak.toString());
					respSt = json_bak.toString();
				} else {
					logger.info(buffer);
					respSt = buffer;
				}
			}
			get.abort();
			return respSt;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}
	
	private static String executePostHttp(String url, StringEntity s, String dataType) {
		try {
			String respSt = "";
			HttpClient client = getDefaultHttpClient();
			HttpPost post = new HttpPost(url);
			client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);// 连接时间
			client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);// 读数据超时时间
			s.setContentEncoding(CHARSET);
			if (dataType.equalsIgnoreCase("JSON")) {
				s.setContentType("application/json");// 发送json数据需要设置contentType
			} else if (dataType.equalsIgnoreCase("XML")) {
				s.setContentType("text/xml");// 发送json数据需要设置contentType
			}
			post.setEntity(s);
			
			HttpResponse response = client.execute(post);
			HttpEntity entity = response.getEntity();
//			BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), CHARSET));
//			String buffer = reader.readLine();
			String buffer = IOUtils.toString(entity.getContent(), "UTF-8");
			if (buffer != null) {
				if (dataType.equalsIgnoreCase("JSON")) {
					JSONObject json_bak = JSONObject.fromObject(buffer);
					logger.info(json_bak.toString());
					respSt = json_bak.toString();
				} else {
					logger.info(buffer);
					respSt = buffer.toString();
				}
			}

			post.abort();
			return respSt;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}
	
	private static String executePostHttp(String url, Map<String, Object> params, String dataType){
		return executePostHttp(url, params, dataType, null);
	}
	private static String executePostHttp(String url, Map<String, Object> oparams, String dataType, PCLParamHandler handler){
		try {
//			ObjectMapper mapper = new ObjectMapper();
//			String string = mapper.writeValueAsString(params);
			// PCL参数加工
			Map<String, Object> params = null;
			if (handler != null) {
				params = handler.handle(oparams);
			} else {
				params = oparams;
			}
			
			String string = com.alibaba.fastjson.JSONObject.toJSONString(params, 
					SerializerFeature.WriteMapNullValue,
					SerializerFeature.WriteNullListAsEmpty,SerializerFeature.WriteNullStringAsEmpty);
			StringEntity s = new StringEntity(string, CHARSET);
			return executePostHttp(url, s, dataType);
		} catch (/*JsonProcessingException e*/Exception e) {
			e.printStackTrace();
		}
		return "";
	}
	
	private static PCLResponseInfo processPCLResponse(String content) {
		ObjectMapper mapper = new ObjectMapper();
		try {
			PCLResponseInfo ri = mapper.readValue(content, PCLResponseInfo.class);
			if (!StringUtils.equals(ri.getMeta().getCode(), PCLResponseInfo.SUCCESS_CODE)) {
				throw new PCLServiceException(ri.getMeta().getCode(), ri.getMeta().getMessage());
			}
			return ri;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	private static CreditResponseInfo processCreditResponse(String content) {
		ObjectMapper mapper = new ObjectMapper();
		if (StringUtils.isBlank(content)) {
			return null;
		}
		try {
			CreditResponseInfo ri = mapper.readValue(content, CreditResponseInfo.class);
			if (!StringUtils.equals(ri.getMeta().getCode(), CreditResponseInfo.SUCCESS_CODE)) {
				throw new PCLServiceException(ri.getMeta().getCode(), ri.getMeta().getMessage());
			}
			return ri;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static String identityHTTPClient(String url, Part[] parts) {
		String result = null;
		PostMethod filePost = new PostMethod(url);
		try {
			filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams()));
			org.apache.commons.httpclient.HttpClient client = new org.apache.commons.httpclient.HttpClient();
			client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
			int status = client.executeMethod(filePost);
			if (status != HttpStatus.SC_OK) {
				throw new CreditException("Http 连接异常");
			}
			result = filePost.getResponseBodyAsString();
			result = new String(result.getBytes("ISO-8859-1"),"utf-8");
		} catch (IOException e) {
			filePost.releaseConnection();
			e.printStackTrace();
		}
		filePost.releaseConnection();
		return result;
	}
	
	public static void main(String[] args) throws IOException {
		System.out.println("请求开始");
		String loanNo = "150402017012602616";
		Map<String, Object> map = new HashMap<>();
		map.put("loanNo",loanNo);
		PCLResponseInfo info = HttpClientUtils.doPCLPost("http://test1.lfrzzlcredit.com/pcl/services/loanCenter/marketing/repayProportionQuery", map);
		System.out.println(info);
	}
}
